package com.product.magina.webserviceclient.wsClient;


import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.util.EntityUtils;
import org.apache.tomcat.util.codec.binary.Base64;
import org.junit.Test;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;

/**
 *  WebServiceClient
 *  Http调用WebService
 *
 * @author anti_magina
 * @date 2019-03-28
 */
@Slf4j
public class WS_Http_Client {

    @Test
    public void test001() {
        //自定义入参格式 以及拼接参数
        String soapParam = soapStr.replace("PARAM", "十大");
        String str = doWsByUrlConnect("http://localhost:8081/services", "TestService", soapParam);
        System.out.println(str);
    }

    @Test
    public void test002() {
        String soapParam = soapStr.replace("PARAM", "十大2");
        //貌似是通过soapParam 去自动识别methodName
        String str = doWsByHttpClient("http://localhost:8081/services/TestService?wsdl", soapParam);
        System.out.println(str);
    }

    @Test
    public void test003() {
        String soapParam = soapStr.replace("PARAM", "十大3");
        String str = doWsByHttpClientFinal("http://localhost:8081/services/TestService", soapParam, null, null);
        System.out.println(str);
    }


    private static final String CHARSET_NAME = "UTF-8";

    private static final String soapStr = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ser=\"http://service.webserviceclient.magina.product.com\">\n" +
            "   <soapenv:Header/>\n" +
            "   <soapenv:Body>\n" +
            "      <ser:sendMessageByUsername>\n" +
            "         <!--Optional:-->\n" +
            "         <username>" + "PARAM" + "</username>\n" +
            "      </ser:sendMessageByUsername>\n" +
            "   </soapenv:Body>\n" +
            "</soapenv:Envelope>";

    /**
     * HttpURLConnection拼接和解析报文进行调用
     *
     * @param url 接口路劲(非wsdl地址)
     * @param method 方法名称
     * @param soap 入参
     * @return
     */
    public String doWsByUrlConnect(String url, String method, String soap) {
        URL wsUrl;
        int errCode = 0;
        JSONObject resultJson = new JSONObject();
        String result = "";
        try {
            wsUrl = new URL(url + "/" + method);
            HttpURLConnection conn = (HttpURLConnection) wsUrl.openConnection();
            conn.setDoInput(true);
            conn.setDoOutput(true);
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Content-Type", "text/xml;charset=UTF-8");
            conn.setConnectTimeout(2000);
            conn.setReadTimeout(2000);
            OutputStream os = conn.getOutputStream();
            //请求体
            os.write(soap.getBytes());
            InputStream is = conn.getInputStream();
            byte[] b = new byte[1024];
            int len = 0;
            String s = "";
            while ((len = is.read(b)) != -1) {
                String ss = new String(b, 0, len, "UTF-8");
                s += ss;
            }
//                result=s.split("<response xsi:type=\"xsd:string\">")[1].split("</response>")[0];
            result = s.split("<sendMessageResult>")[1].split("</sendMessageResult>")[0];
            is.close();
            os.close();
            conn.disconnect();
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            System.out.println("通讯模块1:" + e.getMessage());
            errCode = 1;
        } catch (IOException e) {
            // TODO Auto-generated catch block
            System.out.println("通讯模块2:" + e.getMessage());
            errCode = 2;
        }
        resultJson.put("errCode", errCode);
        resultJson.put("data", result);
        return resultJson.toString();
    }

    /**
     * httpClient可以算是加强版的HttpURLConnection，
     * httpClient的API比较多，也比较稳定，不容易扩展。
     * HttpURLConnection比较轻量级，容易根据自己的需求进行扩展。
     * 但是稳定性不如httpClient。
     *
     * @param url wsdl地址
     * @param soap 入参
     * @return
     */
    public String doWsByHttpClient(String url, String soap) {

        HttpClient httpClient = new HttpClient();
        PostMethod postMethod = new PostMethod();
        postMethod.setPath(url); //路径和wsdl名
        JSONObject resultJson = new JSONObject();

//        String soap = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" "
//                + "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><soapenv:Body><ns1:GetNcgOnlineInfo soapenv:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\" xmlns:ns1=\"urn:ncg\"/></soapenv:Body></soapenv:Envelope>";

        try {
            byte[] b = soap.getBytes("utf-8");
            InputStream is = new ByteArrayInputStream(b, 0, b.length);
            RequestEntity re = new InputStreamRequestEntity(is, b.length,
                    "application/soap+xml; charset=utf-8");
            postMethod.setRequestEntity(re);
            int statusCode = httpClient.executeMethod(postMethod);
            String soapResponseData = postMethod.getResponseBodyAsString();
            postMethod.releaseConnection();
            //解析
            resultJson.put("errCode", statusCode);
            resultJson.put("data", soapResponseData);
        } catch (UnsupportedEncodingException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        } catch (HttpException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return resultJson.toString();

    }

    /**
     *  优化版
     * @param url 接口地址(非wsdl地址)
     * @param soap
     * @param username 可为空
     * @param password
     * @return
     */
    public String doWsByHttpClientFinal(String url, String soap, String username, String password) {
        CloseableHttpClient httpclient = HttpClients.createDefault();
        String retStr = "";
        CloseableHttpResponse response = null;
        try {
            HttpEntity data = new StringEntity(soap, Charset.forName("UTF-8"));
            HttpPost httpPost = new HttpPost(url);
            //  设置请求和传输超时时间
            RequestConfig requestConfig = RequestConfig.custom()
                    .setSocketTimeout(2000)
                    .setConnectTimeout(2000).build();
            httpPost.setConfig(requestConfig);
            httpPost.addHeader("Content-Type", "application/soap+xml;charset=UTF-8");
            httpPost.addHeader(new BasicHeader("Authorization", "Basic " + Base64.encodeBase64String((username + ":" + password).getBytes())));
            httpPost.setEntity(data);
            response = httpclient.execute(httpPost);
            HttpEntity httpEntity = response.getEntity();
            if (httpEntity != null) {
                retStr = EntityUtils.toString(httpEntity, "UTF-8");
            }
        } catch (Exception e) {
            log.error("使用HttpPost传输XML格式字符串失败：" + e);
        } finally {
            // 关闭连接,释放资源3
            try {
                if (response != null) response.close();
                if (httpclient != null) httpclient.close();
            } catch (IOException e) {
            }
        }
        return retStr;
    }

}